import sys
parent_dir = "../pygl"
sys.path.append(parent_dir)
import ctypes
import OpenGL.GL as gl
import glm
import imgui
import glfw
from glfw import _GLFWwindow as GLFWwindow
import numpy as np
import pygl
from common import AppWithTrackball, Sphere, AxesHelper

class SphereApp(AppWithTrackball):
    # 初始化着色器，vao vbo等
    def setupVertex(self) -> None:
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glEnable(gl.GL_CULL_FACE)
        gl.glPatchParameteri(gl.GL_PATCH_VERTICES, 3)
        self.program = pygl.ProgramVFTG("intermediate/shaders/pipeline.vs", 
                                      "intermediate/shaders/pipeline.fs",
                                      "intermediate/shaders/pipeline.tcs",
                                      "intermediate/shaders/pipeline.tes",
                                      "intermediate/shaders/pipeline.geom")
        self.background_color = glm.vec4(0.9, 0.9, 0.9, 1.0)
        self.world_axes = AxesHelper(1.5, 5.0)
        self.show_world_axes = True
        self.imgui_window_width = 250
        self.imgui_window_height = 150
        self.inner_level = 3.0
        self.outer_level = 2.0
        self.ambient_mat = glm.vec3(0.04, 0.04, 0.04)
        self.diffuse_mat = glm.vec3(0.0, 0.75, 0.75)
        self.light_position = glm.vec3(0.25, 0.25, -1.0)
        vertices = np.array([
            0.000,  0.000,  1.000,
            0.894,  0.000,  0.447,
            0.276,  0.851,  0.447,
            -0.724,  0.526,  0.447,
            -0.724, -0.526,  0.447,
            0.276, -0.851,  0.447,
            0.724,  0.526, -0.447,
            -0.276,  0.851, -0.447,
            -0.894,  0.000, -0.447,
            -0.276, -0.851, -0.447,
            0.724, -0.526, -0.447,
            0.000,  0.000, -1.000
        ], dtype=gl.GLfloat)
        self.indices = np.array([
            2, 1, 0,
            3, 2, 0,
            4, 3, 0,
            5, 4, 0,
            1, 5, 0,
            11, 6,  7,
            11, 7,  8,
            11, 8,  9,
            11, 9,  10,
            11, 10, 6,
            1, 2, 6,
            2, 3, 7,
            3, 4, 8,
            4, 5, 9,
            5, 1, 10,
            2,  7, 6,
            3,  8, 7,
            4,  9, 8,
            5, 10, 9,
            1, 6, 10            
        ], dtype=gl.GLuint)
        attribute_position = pygl.VertexAttribute("position", 0, 3, gl.GL_FLOAT, False, 0)
        vaoBindingPoint = 0
        self.vao = pygl.VertexArrayObject()
        self.vbo = pygl.VertexBufferObject(vertices)
        self.ebo = pygl.ElementBufferObject(self.indices)
        self.vao.setVertexBuffer(self.vbo, vaoBindingPoint, 0, 3 * gl.sizeof(gl.GLfloat))
        self.vao.setVertexAttribute(vaoBindingPoint, attribute_position)
        self.vao.setElementBuffer(self.ebo)

    # 配置imgui界面元素
    def showImGui(self)->None:
        imgui.begin("设置")
        if imgui.button("重置"):
            self.camera.reset(glm.vec3(0.0, 0.0, 3.0), glm.vec3(0.0, 0.0, 0.0), 
                    glm.vec3(0.0, 1.0, 0.0))
        _, self.inner_level =  imgui.slider_int("内侧层级", self.inner_level, 1, 10)
        _, self.outer_level =  imgui.slider_int("外侧层级", self.outer_level, 1, 10)
        _, self.show_world_axes = imgui.checkbox("显示三维世界坐标轴", 
                                                self.show_world_axes)
        imgui.end()       

    # 渲染图形
    def render(self) -> None:
        gl.glClearBufferfv(gl.GL_COLOR, 0, self.background_color.to_tuple())
        gl.glClearBufferfv(gl.GL_DEPTH, 0, 1.0)
        self.view = self.camera.getViewMatrix()
        self.projection = self.camera.getProjectionMatrix()
        self.model = glm.mat4(1.0)
        self.program.use()
        self.program.setUniform1f(0, self.inner_level)
        self.program.setUniform1f(1, self.outer_level)
        self.program.setUniformMatrix4fv(2, self.model)
        self.program.setUniformMatrix4fv(3, self.view)
        self.program.setUniformMatrix4fv(4, self.projection)
        self.program.setUniform3fv(5, self.light_position)
        self.program.setUniform3fv(6, self.diffuse_mat)
        self.program.setUniform3fv(7, self.ambient_mat)
        self.vao.bind()        
        gl.glDrawElements(gl.GL_PATCHES, self.indices.size, gl.GL_UNSIGNED_INT,None)
        if self.show_world_axes:
            self.world_axes.updateModelMatrix
            self.world_axes.render(self.view, self.projection)

    # 释放资源
    def cleanup(self) -> None:
        self.vao.delete()
        self.vbo.delete()
        self.ebo.delete()
        self.world_axes.delete()
        self.program.delete()

    def mouse_move(self, window:GLFWwindow, x:float, y:float)->None:
        if imgui.is_any_item_active():
            return
        super().mouse_move(window, x, y)

if __name__ == "__main__":
    app = SphereApp(100, 100, 1000, 600, "你好，完整渲染管线App！")
    app.run()


